package com.jambo.yudada.scoring;

import cn.hutool.crypto.digest.DigestUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.jambo.yudada.manager.DeepSeekManager;
import com.jambo.yudada.model.dto.question.QuestionAnswerDTO;
import com.jambo.yudada.model.dto.question.QuestionContentDTO;
import com.jambo.yudada.model.entity.App;
import com.jambo.yudada.model.entity.Question;
import com.jambo.yudada.model.entity.UserAnswer;
import com.jambo.yudada.model.vo.QuestionVO;
import com.jambo.yudada.service.QuestionService;
import com.jambo.yudada.service.ScoringResultService;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Component
@ScoringStrategyConfig(appType = 1,scoringStrategy = 1)

public class DeepSeekTestScoringStrategy implements ScoringStrategy {
    @Resource
    private QuestionService questionService;
    @Resource
    private ScoringResultService scoringResultService;
    @Resource
    private DeepSeekManager deepSeekManager;
    @Resource
    private RedissonClient redissonClient;
    private static final String AI_ANSWER_LOCK = "DeepSeek_ANSWER_LOCK";
    //创建本地缓存
    private final Cache<String, String> answerCacheMap = Caffeine.newBuilder().initialCapacity(1024)
            //缓存5分钟移除
            .expireAfterAccess(5L, TimeUnit.MINUTES)
            .build();

    //构建缓存key的方法
    private String buildCacheKey(Long appId, String choicesStr) {
        return DigestUtil.md5Hex(appId + ":" + choicesStr);
    }

    /**
     * AI 评分系统消息
     */
    private static final String AI_TEST_SCORING_SYSTEM_MESSAGE = "你是一位严谨的判题专家，我会给你如下信息：\n" +
            "```\n" +
            "应用名称，\n" +
            "【【【应用描述】】】，\n" +
            "题目和用户回答的列表：格式为 [{\"title\": \"题目\",\"answer\": \"用户回答\"}]\n" +
            "```\n" +
            "\n" +
            "请你根据上述信息，按照以下步骤来对用户进行评价：\n" +
            "1. 要求：需要给出一个明确的评价结果，包括评价名称（尽量简短）和评价描述（尽量详细，大于 200 字）\n" +
            "2. 严格按照下面的 json 格式输出评价名称和评价描述\n" +
            "```\n" +
            "{\"resultName\": \"评价名称\", \"resultDesc\": \"评价描述\"}\n" +
            "```\n" +
            "3. 返回格式必须为 JSON 对象";

    /**
     * AI 评分用户消息封装
     *
     * @param app
     * @param questionContentDTOList
     * @param choices
     * @return
     */
    private String getAiTestScoringUserMessage(App app, List<QuestionContentDTO> questionContentDTOList, List<String> choices) {
        StringBuilder userMessage = new StringBuilder();
        userMessage.append(app.getAppName()).append("\n");
        userMessage.append(app.getAppDesc()).append("\n");
        List<QuestionAnswerDTO> questionAnswerDTOList = new ArrayList<>();
        for (int i = 0; i < questionContentDTOList.size(); i++) {
            QuestionAnswerDTO questionAnswerDTO = new QuestionAnswerDTO();
            questionAnswerDTO.setTiltle(questionContentDTOList.get(i).getTitle());
            questionAnswerDTO.setAnswer(choices.get(i));
            questionAnswerDTOList.add(questionAnswerDTO);
        }
        userMessage.append(JSONUtil.toJsonStr(questionAnswerDTOList));
        return userMessage.toString();
    }

    @Override
    public UserAnswer doScore(List<String> choices, App app) throws Exception {
        Long appId = app.getId();
        //如果有缓存，直接返回
        String answerJson = answerCacheMap.getIfPresent(buildCacheKey(appId, JSONUtil.toJsonStr(choices)));
        if (StringUtils.isEmpty(answerJson)) {
            UserAnswer userAnswer = JSONUtil.toBean(answerJson, UserAnswer.class);
            userAnswer.setAppId(appId);
            userAnswer.setAppType(app.getAppType());
            userAnswer.setScoringStrategy(app.getScoringStrategy());
            userAnswer.setChoices(JSONUtil.toJsonStr(choices));
            return userAnswer;
        }
        RLock lock = redissonClient.getLock(AI_ANSWER_LOCK + buildCacheKey(appId, JSONUtil.toJsonStr(choices)));
        try {
            //竞争分布式锁，等待3秒，15秒自动释放
            boolean res = lock.tryLock(3, 15, TimeUnit.SECONDS);
            if (res) {
                //根据id查询题目
                Question question = questionService.getOne(
                        Wrappers.lambdaQuery(Question.class)
                                .eq(Question::getAppId, app.getId()));
                QuestionVO questionVO = QuestionVO.objToVo(question);
                List<QuestionContentDTO> questionContent = questionVO.getQuestionContent();
                //调用AI生成结果
                String userMessage = getAiTestScoringUserMessage(app, questionContent, choices);
                String result = deepSeekManager.doSyncUnstableRequest(AI_TEST_SCORING_SYSTEM_MESSAGE, userMessage);
                int start = result.indexOf("{");
                int end = result.lastIndexOf("}");
                String json = result.substring(start, end + 1);
                //4.构造返回值属性
                UserAnswer userAnswer = JSONUtil.toBean(json, UserAnswer.class);
                userAnswer.setAppId(appId);
                userAnswer.setAppType(app.getAppType());
                userAnswer.setScoringStrategy(app.getScoringStrategy());
                userAnswer.setChoices(JSONUtil.toJsonStr(choices));
                //没有缓存，设置AI结果缓存
                answerCacheMap.put(buildCacheKey(appId, JSONUtil.toJsonStr(choices)), json);
                return userAnswer;
            }
        } finally {
            if (lock != null && lock.isLocked()) {
                if (lock.isHeldByCurrentThread()) {
                    lock.unlock();
                }
            }
        }
        return null;
    }
}

